package com.charging.common;

import com.alibaba.fastjson.JSONObject;

import com.charging.common.constant.Constants;
import com.charging.common.core.redis.RedisCache;
import com.charging.common.utils.DateUtils;
import com.charging.common.utils.http.HttpUtils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 微信公众号服务相关的方法
 */
@Component("WePublicUtils")
public class WePublicUtils {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    // redis操作
    @Resource
    public RedisCache redisCache;

    //获取 用户的认证token
    private String AccessTokenHost = "https://api.weixin.qq.com/sns/oauth2/access_token";
    // 获取微信的 accessToken
    private String AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";

    // 获取微信 ticket
    private String TicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    // 获取微信获取微信用户信息的请求地址
    public String UserInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info";
    // 微信消息模板发送地址
    public String MsgTemplateUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send";


    /**
     * 检测客户端范围类型
     * @return
     */
    public int checkRequestClient(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String userAgent = request.getHeader("user-agent");
        if (userAgent != null && userAgent.contains("MicroMessenger")){
            return Constants.TranType.WEIXIN; // 微信
        }else if (userAgent !=null && userAgent.contains("AlipayClient")){
            return Constants.TranType.ALIPALY; // 支付宝
        }
        return Constants.TranType.NOKNOW;

    }


    /**
     * 获取 微信的 access token，获取用户信息。目的判断用户是否关注公众号
     * @return
     */
    public String getWePublicAccessToken(String AppId,String WxAppSecret){
        String access_token = redisCache.getCacheObject(Constants.REDIS_KEY_WE_PUBLIC_ACCESS_TOKEN+"_"+AppId);
        if(null == access_token){
            String param = "appid=" + AppId;
            param += "&secret=" + WxAppSecret;
            param += "&grant_type=client_credential";
            String res = HttpUtils.sendGet(AccessTokenUrl,param);
            logger.info("获取微信公众号客户端 accessToken 返回结果: {}",res);

            JSONObject resJson = JSONObject.parseObject(res);
            if (!resJson.containsKey("errcode")) {
                access_token = resJson.getString("access_token");
                logger.info("获取微信公众号客户端 accessToken : {}",access_token);
                redisCache.setCacheObject(Constants.REDIS_KEY_WE_PUBLIC_ACCESS_TOKEN+"_"+AppId,access_token,7000, TimeUnit.SECONDS);
            }

        }
        return access_token;
    }

    /**
     * 获取微信ticket
     *
     * @return
     */
    public String getWePublicTicket(String appId,String WxAppSecret){
        String ticket = redisCache.getCacheObject(Constants.REDIS_KEY_WE_PUBLIC_TICKET+"_"+appId);
        if(StringUtils.isEmpty(ticket)){
            String param = "access_token=" + getWePublicAccessToken(appId,WxAppSecret);
            param += "&type=jsapi";
            String res = HttpUtils.sendGet(TicketUrl,param);
            logger.info("获取微信公众号客户端Ticket返回结果: {}",res);
            JSONObject resJson = JSONObject.parseObject(res);
            if (StringUtils.isNotEmpty(resJson.getString("ticket"))) {
                ticket = resJson.getString("ticket");
                logger.info("获取微信公众号客户端 ticket : {}",ticket);
                redisCache.setCacheObject(Constants.REDIS_KEY_WE_PUBLIC_TICKET+"_"+appId,ticket,7000, TimeUnit.SECONDS);
            }
        }
        return ticket;
    }

    // 微信请求签名
    public JSONObject getWeSign(String url,String appId,String WxAppSecret){
        JSONObject ret = new JSONObject();
        String nonce_str = UUID.randomUUID().toString().replace("-", "");//产生随机串--由程序自己随机产生
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);//由程序自己获取当前时间

        String string1;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        String ticket = getWePublicTicket(appId,WxAppSecret);
        string1 = "jsapi_ticket=" + ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + (url.indexOf("#") >= 0 ? url.substring(0, url.indexOf("#")) : url);
        System.out.println(string1);
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ret.put("url", url);
        ret.put("jsapi_ticket", ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 获取微信公众号的用户信息
     * @param openid
     * @return
     */
    public String getWePublicUserInfo(String openid,String AppId,String WxAppSecret){
        String accessToken = getWePublicAccessToken(AppId,WxAppSecret);
        String param = "access_token=" + accessToken;
        param += "&openid=" + openid;
        param += "&lang=zh_CN";
        String res = HttpUtils.sendGet(UserInfoUrl,param);
        logger.info("通过{}获取的用户信息：{}",openid,res);
        return res;
    }

    /**
     * 通过用户的code 获取用户openid
     * @param code
     * @return
     */
    public String getWePublicOpenId(String code,String appId,String WxAppSecret){

        String param = "appid=" + appId;
        param += "&secret=" + WxAppSecret;
        param += "&code=" + code; //微信反馈的code
        param += "&grant_type=authorization_code";
        String res = HttpUtils.sendGet(AccessTokenHost,param);
        logger.info("获取访问用户的OpenId返回结果: {}",res);
        return  res;
    }

    /**
     * 微信公众号获取用户详细信息，用户需要同意获取
     * @param code
     * @param wxAppId
     * @param wxAppSecret
     * @return
     */
    public String getWeUserSubInfo(String code, String wxAppId, String wxAppSecret) {
        String param = "appid=" + wxAppId;
        param += "&secret=" + wxAppSecret;
        param += "&code=" + code;
        param += "&grant_type=authorization_code";
        String res = HttpUtils.sendGet(AccessTokenHost,param);
        logger.info("获取微信公众号客户端 accessToken 返回结果: {}",res);
        return res;
    }


    /**
     * 微信消息
     */
    public class TemplateData {
        private String value;
        private String color;
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
        public String getColor() {
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
    }
    public class WxTemplate {
        /**
         * 模板消息id
         */
        private String template_id;
        /**
         * 用户openId
         */
        private String touser;
        /**
         * URL置空，则在发送后，点击模板消息会进入一个空白页面（ios），或无法点击（android）
         */
        private String url;
        /**
         * 标题颜色
         */
        private String topcolor;
        /**
         * 详细内容
         */
        private Map<String,TemplateData> data;

        public String getTemplate_id() {
            return template_id;
        }
        public void setTemplate_id(String template_id) {
            this.template_id = template_id;
        }
        public String getTouser() {
            return touser;
        }
        public void setTouser(String touser) {
            this.touser = touser;
        }
        public String getUrl() {
            return url;
        }
        public void setUrl(String url) {
            this.url = url;
        }
        public String getTopcolor() {
            return topcolor;
        }
        public void setTopcolor(String topcolor) {
            this.topcolor = topcolor;
        }
        public Map<String, TemplateData> getData() {
            return data;
        }
        public void setData(Map<String, TemplateData> data) {
            this.data = data;
        }
    }

    /**
     * 充电桩微信结束充电消息提醒
     * @param openId 用户openid
     * @param equipNo 设备号
     * @param startTime 开始时间
     * @param chargingTime 充电时长
     * @param amount 金额
     * @param endName 结束原因
     * @return
     */
    public boolean sendWeMsgEndCharging(String appId,String WxAppSecret,String WeMsgGoToUrl,String TemplateId,String UserName ,String openId,String equipNo,String maxChargingPower,String balance,String give,
                                        String startTime,String endTime, String chargingTime,String amount,String endName){
        String url = MsgTemplateUrl + "?access_token=" + getWePublicAccessToken(appId,WxAppSecret);
        WxTemplate temp = new WxTemplate();
        temp.setUrl(WeMsgGoToUrl);
        temp.setTouser(openId);
        temp.setTopcolor("#000000");
        temp.setTemplate_id(TemplateId);
        Map<String,TemplateData> m = new HashMap<String,TemplateData>();
        TemplateData first = new TemplateData();
        first.setColor("#000000");
        first.setValue("尊敬的["+UserName+"]充电用户,您本次充电结束，最高充电功率"+maxChargingPower+"瓦。");
        m.put("first", first);
        // 设备名称
        TemplateData name = new TemplateData();
        name.setColor("#000000");
        name.setValue(equipNo);
        m.put("keyword1", name);
        // 告警类型
        TemplateData starttime = new TemplateData();
        starttime.setColor("#000000");
        starttime.setValue(startTime + " 至\n"+endTime);
        m.put("keyword2", starttime);
        // 告警时间
        TemplateData time = new TemplateData();
        time.setColor("#000000");
        time.setValue(chargingTime+"分钟");
        m.put("keyword3", time);
        TemplateData money = new TemplateData();
        money.setColor("#000000");
        money.setValue(amount+"元");
        m.put("keyword4", money);
        TemplateData remark = new TemplateData();
        remark.setColor("#000000");
        remark.setValue("账户余额:"+balance+"元\n赠送余额:"+give+"元\n充电结束原因可能如下:\n【"+endName+"】");
        m.put("remark", remark);
        temp.setData(m);
        String jsonString = JSONObject.toJSONString(temp);
        String res = HttpUtils.sendPost(url,jsonString);
        int result = 0;

        JSONObject resJson = JSONObject.parseObject(res);
        if (0 !=resJson.getIntValue("errcode")) {
            result = resJson.getIntValue("errcode");
            logger.error("错误 errcode:{} errmsg:{}", resJson.getIntValue("errcode"), resJson.getString("errmsg"));
        }

        return result==0;
    }

    /**
     * 设备告警
     * @param openId
     * @param equipNo
     * @param alertName
     * @return
     */
    public boolean sendWeMsgAlertInfo(String appId,String WxAppSecret,String WeMsgGoToUrl,String alertTemplateId,String openId,String equipNo,String alertName){
        String url = MsgTemplateUrl + "?access_token=" + getWePublicAccessToken(appId,WxAppSecret);
        WxTemplate temp = new WxTemplate();
        temp.setUrl(WeMsgGoToUrl);
        temp.setTouser(openId);
        temp.setTopcolor("#000000");
        temp.setTemplate_id(alertTemplateId);
        Map<String,TemplateData> m = new HashMap<String,TemplateData>();
        TemplateData first = new TemplateData();
        first.setColor("#000000");
        first.setValue("尊敬的站长用户,设备号["+equipNo+"]发生["+alertName+"]请尽快处理。");
        m.put("first", first);
        TemplateData name = new TemplateData();
        name.setColor("#000000");
        name.setValue(equipNo);
        m.put("keyword1", name);
        // 告警类型
        TemplateData starttime = new TemplateData();
        starttime.setColor("#fd2636");
        starttime.setValue(alertName);
        m.put("keyword2", starttime);
        // 告警时间
        TemplateData time = new TemplateData();
        time.setColor("#000000");
        time.setValue(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,new Date()));
        m.put("keyword3", time);
        temp.setData(m);
        String jsonString = JSONObject.toJSONString(temp);
        String res = HttpUtils.sendPost(url,jsonString);
        int result = 0;

        JSONObject resJson = JSONObject.parseObject(res);
        if (0 !=resJson.getIntValue("errcode")) {
            result = resJson.getIntValue("errcode");
            logger.error("错误 errcode:{} errmsg:{}", resJson.getIntValue("errcode"), resJson.getString("errmsg"));
        }

        return result==0;
    }


}
